package dominio;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.uqbar.commons.utils.Observable;

import resultado.Derrota;
import resultado.NoPremio;
import resultado.PremioPlanta;
import resultado.PremioPuntos;
import resultado.Resultado;
@Observable
public class Zombie implements Serializable{
	// La vida inicial se setea cuando
	// se asignan los puntos de defensa
	private String nombre ="Zombie";
	private int puntosAtaque, puntosDefensa, vidaInicial;
	
	public Zombie(int pATK, int PDEF) {
		this.vidaInicial = PDEF;
		this.puntosAtaque = pATK;
		this.puntosDefensa =PDEF;
	}

	public Zombie(String nombre, int pATK, int PDEF) {
		this.vidaInicial = PDEF;
		this.nombre = nombre;
		this.puntosAtaque = pATK;
		this.puntosDefensa = PDEF;
	}
	
	/**
	 * Constructor Utilizado para clonar una planta
	 * @param prototype
	 */
	private Zombie(Zombie prototype){
		this.nombre = prototype.getNombre();
		this.puntosAtaque = prototype.getPuntosAtaque();
		this.puntosDefensa = prototype.getVidaInicial();
		this.vidaInicial = prototype.getVidaInicial();
	}
	
	/**
	 * Retorna un clon de Zombie, mismos valores, distinta identidad.
	 * @return Planta
	 */
	public Zombie makeClone(){
		Zombie theClone = new Zombie(this);
		return theClone;
	}

	/**
	 * Atencion!. Sin este metodo, los nombres de cada objeto pueden presentarse
	 * de forma fea en un binding, al estilo "dominio.Zombie@234d4a1a"
	 * De esta forma, el binding toma el nombre de cada objeto correctamente como
	 * queramos nosotros.
	 */
	@Override
	public String toString() {
		return this.getNombre();
	}

	/**
	 * Representacion del combate del zombie y la planta. El zombie recibe una
	 * fila de plantas, el zombie le pide a la fila la primera planta atacable (
	 * la más proxima al zombie), la ataca, luego todas las plantas de la fila
	 * lo atacan. El ciclo se repite hasta que el zombie muere, y se entrega un
	 * premio o bien hasta que no quedan plantas y se devuelve un resultado
	 * Derrota.
	 * 
	 * @param fila
	 * @return
	 */
	public Resultado atacarFila(Fila fila) {
		List<String> plantasPerdidas = new ArrayList<String>();
		// Mientras el zombie viva, ataca a la fila
		while (!this.estaMuerto()) {
			// Si hay defensa, atacarla
			if (!fila.hayPlantas()) {
				// Perdiste! El zombie te comio el cerebro
				return new Derrota(this.getNombre());
			}
			
			Planta plantaVictima = fila.obtenerPrimeraPlantaAtacable();
			this.atacarPlanta(plantaVictima);

			// La fila de plantas ataca al zombie
			this.quitarPuntosDef(fila.puntosAtaquePlantas());
			if (plantaVictima.estaMuerta()){
				plantasPerdidas.add(plantaVictima.getNombre());
			}
			fila.sacarPrimeraPlantaSiEstaMuerta();
		}
		
		// Sobreviviste al ataque zombie
		return this.sortearPremioRandom(stringsToString(plantasPerdidas));
	}

	/**
	 * Algoritmo para el sorteo del premio.
	 * 
	 * 1º Paso, <= 50% probabilidad de obtener Premio, caso contrario obtiene un
	 * noPremio.
	 * 
	 * 2º Paso, <= 25% probabilidad de obtener una planta, caso contrario se
	 * obtiene una cantidad de puntos de 1 al tercio de la vida inicial del
	 * zombie eliminado. Nota: hay dos posibles
	 * 
	 * La "acreditacion" del premio la ejecuta la clase juego
	 * 
	 * 
	 * 
	 * @return Resultado
	 */
	public Resultado sortearPremioRandom(String msgplantasPerdidas) {

		double daPremio = Math.random(); // obtengo un valor entre 0,1

		// Chances de ganar premio = 50%, implica valor igualo mayor a 0.5
		if (daPremio >= 0.5) {
			
			// Has recibido un premio por matar al zombie!
			double daPlanta = Math.random();
			
			// (Chances 25% o menos de ganar planta)			
			if (daPlanta <= 0.25) {				
				// Ganas una planta para tu jardin Zen!!
				
				return new PremioPlanta(msgplantasPerdidas, this.nombre);
			// Resto de las posibilidades, ganas puntos
			} else {
				Random rand = new Random();
				int puntosPremio = rand.nextInt(this.vidaInicial /3 ) + 1;

				// Has ganado puntos
				return new PremioPuntos(puntosPremio , msgplantasPerdidas, this.nombre);
			}
		}

		return new NoPremio(msgplantasPerdidas, this.nombre);
	}
	
	public String stringsToString(List<String>sts){
		
		String x = "";
		if(sts.isEmpty()){
			x = "No has perdido plantas" ;
			return x;
		}else{
			x = "Has perdido estas plantas: " ;
			for (String string : sts) {
				x = x.concat(string + ", \n ");
			}
			return x;
		}
		
	}
	
	public void atacarPlanta(Planta p) {
		p.quitarPuntosDef(this.getPuntosAtaque());
	}

	public void quitarPuntosDef(int ataque) {

		this.puntosDefensa = this.puntosDefensa - ataque;
		if (this.puntosDefensa <= 0) {
			this.puntosDefensa = 0;

		}
	}

	public int getVidaInicial() {
		return vidaInicial;
	}

	public void setVidaInicial(int vidaInicial) {
		this.vidaInicial = vidaInicial;
	}

	public boolean estaMuerto() {
		return this.puntosDefensa <= 0;
	}

	public String getNombre() {
		return this.nombre;
	}
	
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public int getPuntosAtaque() {
		return puntosAtaque;
	}

	public void setPuntosAtaque(int puntosAtaque) {
		this.puntosAtaque = puntosAtaque;
	}

	public int getPuntosDefensa() {
		return puntosDefensa;
	}

	public void setPuntosDefensa(int puntosDefensa) {
		this.puntosDefensa = puntosDefensa;
		
	}
}
